﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Fuse8.ContentManagementFramework.BizFacade.Services.Contents;
using Fuse8.ContentManagementFramework.SystemFacade.Contents;
using Fuse8.DomainFramework.Common.Locator;
using Telerik.Web.Mvc;

using Fuse8.ContentManagementFramework.BizFacade.Services;
using Fuse8.ContentManagementFramework.Domain;
using Fuse8.ContentManagementFramework.Domain.Special;
using Fuse8.ContentManagementFramework.SystemFacade;
using Fuse8.ContentManagementFramework.Administration.Models;
using Fuse8.ContentManagementFramework.Web.Etc;

namespace Fuse8.ContentManagementFramework.Administration.Controllers
{
    public class CmsContentTypeController : CmsAdminController<CmsContentType>
    {
        private CmsContentTypeService _contentTypeService;

        protected virtual CmsContentTypeService ContentTypeService
        {
            get
            {
                if (_contentTypeService == null)
                {
                    _contentTypeService = new CmsContentTypeService();
                }

                return _contentTypeService;
            }
        }
        
        public virtual ActionResult Index(int? pageSize)
        {
            int currentPageSize = pageSize ?? DefaultPageSize;

            var data = ContentTypeService.FindAllNonSystem();

            ViewBag.PageSize = currentPageSize;
            ViewBag.Total = data.Count();

            return View(data);
        }

        [GridAction]
        public virtual ActionResult _Index(int? pageSize)
        {
            var data = ContentTypeService.FindAllNonSystem();

            return View(
                   new GridModel<CmsContentType>
                   {
                       Data = data
                   });
        }

        public virtual ActionResult Add()
        {
            return View();
        }

        [HttpPost]
        public virtual ActionResult Add(CmsContentTypeModel model)
        {
            ActionResult result = null;

            if (model != null)
            {
                if (ModelState.IsValid)
                {
                    var type = model.ToDomainEntity();
                    ContentTypeService.Add(type);
                    ContentSchemeManager.ChangeSchemeForType(type.Id);
                    result = RedirectToAction("Index");
                }
            }

            return result ?? View(model);
        }

        public ActionResult EditDetails(int id)
        {
            return View(ContentTypeService.FindOne(id));
        }

        [HttpPost]
        public virtual ActionResult EditDetails(CmsContentTypeModel model)
        {
            ActionResult result = null;

            if (model != null)
            {
                if (ModelState.IsValid)
                {
                    ContentTypeService.Save(model.ToDomainEntity());

                    result = RedirectToAction("Edit", new {id = model.Id});
                }
            }

            return result ?? View(model);
        }

        public virtual ActionResult Edit(int id, bool isInAjax = false, int page = 1)
        {
            ActionResult result = null;
            ViewBag.IsInAjax = isInAjax;
            if (id > 0)
            {
                var data = ContentTypeService.FindOne(id);
                if (data != null)
                {
                    result = !isInAjax ? View(data) : (ActionResult) PartialView(data);
                }
            }

            return result ?? RedirectToAction("Index");
        }

        public virtual ActionResult ContentTypeDetails(int id)
        {
            var model = new CmsContentTypeModel();
            model.Init(id);
            return PartialView(model);
        }

        public virtual ActionResult AllCategories(int id)
        {
            ViewBag.ContentTypeId = id;

            new CmsAdminContentCategoryModel { ContentTypeId = id }.SaveMemento();

            CmsContentType contentType;

            return PartialView(GetContentTypeCategories(id, out contentType));
        }

        public ActionResult MetaFields(int id)
        {
            var type = ContentTypeService.FindOne(id);
            return View(type);
        }

        [HttpGet]
        public ActionResult AddMeta(int typeId)
        {
            return new CmsContentMetaController(typeId).Add();
        }

        [HttpPost]
        public ActionResult AddMeta(CmsEntityMetaFieldLinkModel model, int typeId, [ModelBinder(typeof(EntityMetaLinkValuesBinder))]string valueSettings)
        {
            var actionResult = new CmsContentMetaController(typeId).Add(model, valueSettings);
            if (ModelState.IsValid)
            {
                ContentSchemeManager.ChangeSchemeForType(typeId);
            }
            return actionResult;
        }

        [HttpGet]
        public ActionResult EditMeta(int typeId, int id)
        {
            return new CmsContentMetaController(typeId).Edit(id);
        }

        [HttpPost]
        public ActionResult EditMeta(CmsEntityMetaFieldLinkModel model, int typeId, [ModelBinder(typeof(EntityMetaLinkValuesBinder))]string valueSettings)
        {
            var actionResult = new CmsContentMetaController(typeId).Edit(model, valueSettings);

            if (ModelState.IsValid)
            {
                ContentSchemeManager.ChangeSchemeForType(typeId);
            }
            
            return actionResult;
        }

        [GridAction]
        public virtual ActionResult _AllCategories(int id)
        {
            ViewBag.ContentTypeId = id;

            CmsContentType contentType;

            return PartialView(
                   new GridModel<CmsContentTypeCategory>
                   {
                       Data = GetContentTypeCategories(id, out contentType)
                   });
        }

        protected override bool _Delete(int id)
        {
            ContentTypeService.Remove(id);
            return true;
        }

        protected virtual IEnumerable<CmsContentTypeCategory> GetContentTypeCategories(int id, out CmsContentType contentType)
        {
            IEnumerable<CmsContentTypeCategory> result = null;

            contentType = null;

            if (id > 0)
            {
                contentType = ContentTypeService.FindOne(id);
                if (contentType != null)
                {
                    var categoryContainer = contentType.GetMetaValue<CmsContentTypeCategoryContainer>(CmsConfiguration.ContentTypeCategoryMetaFieldName);
                    if (categoryContainer != null)
                    {
                        result = categoryContainer.Categories;
                    }
                }
            }

            return result ?? new List<CmsContentTypeCategory>();
        }

        protected override bool _AddCategory(string categoryName)
        {
            bool result = false;

            var contentCategory = new CmsAdminContentCategoryModel().RestoreMemento();

            if (contentCategory != null)
            {
                CmsContentType contentType;
                var categories = GetContentTypeCategories(contentCategory.ContentTypeId, out contentType);
                if (contentType != null)
                {
                    int nextId = categories.Count() + 1;

                    contentType.SetMetaValue(
                        CmsConfiguration.ContentTypeCategoryMetaFieldName,
                        new CmsContentTypeCategoryContainer
                        {
                            Categories = categories.Concat(
                                new CmsContentTypeCategory[] 
                                {
                                    new CmsContentTypeCategory
                                    {
                                        Id = nextId,
                                        Category = categoryName
                                    }
                                }).ToArray(),
                        },
                        true);

                    result = true;
                }
            }

            return result;
        }

        public ActionResult GetAddtionalViewForm(string name)
        {
            return new CmsContentMetaController(0).GetAddtionalViewForm(name);
        }

        public ActionResult RebuildView(int id)
        {
            //todo: allow to developer super user only
            ContentSchemeManager.ChangeSchemeForType(id);
            return RedirectToAction("Edit", new {id});
        }
    }

    internal class CmsContentMetaController : CmsBaseEntityMetaFieldLinkController
    {
        private readonly int typeId;

        public CmsContentMetaController(int typeId)
        {
            this.typeId = typeId;
        }

        protected override string TypeParameter
        {
            get { return CmsConstants.ContentParameter + typeId; }
        }

        protected override string IndexUrl
        {
            get { return "/admin/cmscontenttype/metafields/" + typeId; }
        }
    }
}
